package spring.cloud.tasks.executor.executor;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.recipes.cache.NodeCache;
import org.apache.curator.framework.recipes.cache.NodeCacheListener;
import spring.cloud.tasks.executor.utils.log.LogEvents;
import spring.cloud.tasks.executor.utils.log.LogUtils;
import spring.cloud.tasks.executor.utils.zookeeper.Zookeeper;

@Slf4j
@Setter
@Getter
public class ExecutorRestartService {
    private String executorId;
    private Zookeeper zookeeper;
    private NodeCache nodeCache;

    public ExecutorRestartService(String executorId, Zookeeper zookeeper) {
        this.executorId = executorId;
        this.zookeeper = zookeeper;
    }

    public void start() throws Exception {
        initExecutorRestartListener();
    }

    public void stop() {
        closeNodeCache(nodeCache);
    }

    private void initExecutorRestartListener() throws Exception {
        // Remove the restart node, before add watcher that watches the create and update event
        String executorRestartNodePath = ExecutorsNode.EXECUTORS_ROOT + "/" + executorId + "/restart";
        zookeeper.delete(executorRestartNodePath);
        nodeCache = new NodeCache(zookeeper.getCuratorFramework(), executorRestartNodePath);
        nodeCache.getListenable().addListener(new NodeCacheListener() {
            @Override
            public void nodeChanged() throws Exception {
                // Watch create, update event
                if (nodeCache.getCurrentData() != null) {
                    LogUtils.info(log, LogEvents.ExecutorEvent.RESTART, "The executor {} restart event is received", executorId);
                    String threadName = executorId + "-restart-thread";
                    Thread thread = new Thread(new Runnable() {
                        @Override
                        public void run() {
                            //重启self
                        }
                    });
                    thread.setName(threadName);
                    thread.setDaemon(true);
                    thread.start();
                }
            }

        });
        // Start, with not buildInitial.
        // The initial data is null, so the create event will be triggered firstly.
        nodeCache.start(false);
    }

    private void closeNodeCache(NodeCache nodeCache) {
        if (nodeCache != null) {
            try {
                nodeCache.close();
            } catch (Exception e) {
                LogUtils.error(log, LogEvents.ExecutorEvent.INIT_OR_SHUTDOWN, e.toString(), e);
            }
        }
    }

}
